package uk.co.javahelp.sender.message.mail;

import java.io.IOException;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

import org.apache.commons.lang3.StringUtils;
import org.springframework.mail.MailException;
import org.springframework.mail.MailPreparationException;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;

import uk.co.javahelp.sender.message.Attachment;
import uk.co.javahelp.sender.message.Message;
import uk.co.javahelp.sender.message.Sender;
import uk.co.javahelp.sender.template.MessageFormatter;

public class MailSender implements Sender {

	private final MessageFormatter messageFormatter;

	private final JavaMailSender javaMailSender;

	private final String fromEmail;

	private final String fromText;

	private final String copyTo;

	public MailSender(
            final MessageFormatter messageFormatter,
			final JavaMailSender javaMailSender,
			final String fromEmail, final String fromText) {
		this(messageFormatter, javaMailSender, fromEmail, fromText, null);
	}

	public MailSender(
            final MessageFormatter messageFormatter,
			final JavaMailSender javaMailSender,
			final String fromEmail, final String fromText, final String copyTo) {
		this.messageFormatter = messageFormatter;
		this.javaMailSender = javaMailSender;
		this.fromEmail = fromEmail;
		this.fromText = fromText;
		this.copyTo = copyTo;
	}

	public void send(Message message) {
		try {
			final String[] subjectTextAndHtml = this.messageFormatter.formatMessage(message);
			final String subject = subjectTextAndHtml[0];
			final String text = subjectTextAndHtml[1];
			final String html = subjectTextAndHtml[2];

			if (StringUtils.isBlank(html)) {
				// Send a plain text only email
				final SimpleMailMessage msg = new SimpleMailMessage();
				msg.setFrom(this.fromEmail);
				msg.setTo(message.getTo());
				if (message.getCc() != null) {
					msg.setCc(message.getCc());
				}
				msg.setSubject(subject);
				msg.setText(text);
				if (StringUtils.isNotBlank(this.copyTo)) {
					msg.setBcc(this.copyTo);
				}
				this.javaMailSender.send(msg);
			} else {
				// Send a multi-part text + html email
				final MimeMessage mime = this.javaMailSender
						.createMimeMessage();
				final MimeMessageHelper helper = new MimeMessageHelper(mime,
						true);

				helper.setFrom(this.fromEmail, this.fromText);
				helper.setTo(message.getTo());
				if (message.getCc() != null) {
					helper.setCc(message.getCc());
				}
				helper.setSubject(subject);
				helper.setText(text, html);
				for (final Attachment attachment : message.getAttachmentList()) {
					helper.addAttachment(attachment.getFilename(),
							attachment.getContent());
				}
				if (StringUtils.isNotBlank(this.copyTo)) {
					helper.setBcc(this.copyTo);
				}

				this.javaMailSender.send(mime);
			}
		} catch (IOException e) {
			throw new MailPreparationException(
					"Cannot construct mail message fromEmail template", e);
		} catch (MessagingException e) {
			throw new MailPreparationException(
					"Cannot construct MIME mail message fromEmail template", e);
		} catch (IllegalStateException e) {
			throw new MailPreparationException(
					"Cannot construct MIME mail message fromEmail template", e);
		} catch (MailException e) {
			// TODO: Implement retry?
			throw e;
		}
	}
}
